package com.bosssoft.hr.train.j2se.collection;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Class ThreadArrayListDemo
 * @Description 创建2个 线程一个做为生产者插入数据到ArrayList另外一个线程作为消费者从队列尾巴删除数据，要求使用synchronized
 * 或者 java的锁控制程序避免冲突，提示：Collections.synchronizedList(list)可以将非现场安全的list转化为线程安全
 * @Author TangZaoBang
 * @Date 2023/04/27 11:20
 * @Version
 */
@Slf4j
public class ThreadArrayListDemo {

    /**
     *     创建线程安全的List对象，可以使用Collections.synchronizedList方法进行转换
      */
    private static List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());

    /**
     * 队列的最大长度
     */
    private static final int MAX_SIZE = 2;

   /**
    * 通过main方法测试是否起作用
    * @author TangZaoBang
    * @date 2023/04/27 12:01
    * @param args
    * @return void
    */
    public static void main(String[] args) {
        producerAndConsumer();
    }
    /**
     * 创建线程池进行操作
     * @author TangZaoBang
     * @date 2023/04/27 11:45
     * @return void
     */
    public static   void producerAndConsumer() {
        // 创建线程
        ThreadFactory threadFactory = new ThreadFactory() {
            private int count = 0;

            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "MyThread-" + count++);
            }
        };
        // 创建线程池，线程池中有2个线程
        ThreadPoolExecutor producerConsumer = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(), threadFactory);
        // 向线程池中添加生产者和消费者任务
        producerConsumer.submit(ThreadArrayListDemo::producer);
        producerConsumer.submit(ThreadArrayListDemo::consumer);
        // 关闭线程池
        producerConsumer.shutdown();
    }
    /**
     * 生产者，利用synchronized锁定
     * @author TangZaoBang
     * @date 2023/04/27 11:47
     * @return void
     */
    public static void producer() {
        int count = 0;
        while (true) {
            synchronized (list) {
                // 如果队列已满，那么生产者线程需要等待
                while (list.size() == MAX_SIZE) {
                    try {
                        list.wait(); // 释放锁并等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 添加元素到队列中
                log.info(Thread.currentThread().getName() + " produced: " + count);
                list.add(count++);
                // 通知正在等待的线程
                list.notifyAll();
            }
        }
    }
    /**
     * 消费者
     * @author TangZaoBang
     * @date 2023/04/27 11:48
     * @return void
     */
    public static void consumer() {
        while (true) {
            synchronized (list) {
                // 如果队列为空，那么消费者线程需要等待
                while (list.isEmpty()) {
                    try {
                        list.wait(); // 释放锁并等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                // 从队列中删除一个元素
                int value = list.remove(list.size() - 1);
               log.info(Thread.currentThread().getName() + " consumed: " + value);
                // 通知正在等待的线程
                list.notifyAll();
            }
        }
    }
}
